﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace DLR04
{
    /// <summary>
    /// A Scope object enumerates the symbols availabe to the executing expression.
    /// </summary>
    /// <remarks>
    /// The GetSymbol method is used by the ExpressionEx.SymbolExpression method to
    /// access a symbol.  The indexer is a convenience tool that the programmer can
    /// use to get and set symbol data.
    /// </remarks>
    public class Scope : IEnumerable<Symbol>
    {
        #region Variables

        private List<Symbol> _list;

        #endregion

        #region Constructors

        public Scope()
        {
            _list = new List<Symbol>();
        }

        #endregion

        #region Properties

        public dynamic this[string name]
        {
            get
            {
                return GetSymbol(name).Data;
            }
            set
            {
                EnsureThatSymbolExists(name);
                _list.Where(x => x.Name == name).First().Data = value;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// This is used by ExpressionEx.SymbolExpression to retrieve a symbol.
        /// </summary>
        public Symbol GetSymbol(string name)
        {
            EnsureThatSymbolExists(name);
            return _list.Where(x => x.Name == name).First();
        }

        public IEnumerator<Symbol> GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        private void EnsureThatSymbolExists(string symbolName)
        {
            if (!_list.Any(x => x.Name == symbolName))
            {
                _list.Add(new Symbol() { Name = symbolName, Data = null });
            }
        }

        #endregion
    }
}